/**
 * Class: Scale
 *
 * Purpose: 
 *
 * Created: Jan 30, 2010 @ 10:22:37 AM
 * @author Ken Scott
 */
package org.openfantasia.musica;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Scale {

	private String name;

	private List<String> toneNames = new ArrayList<String>();

	private List<Double> toneFrequencies = new ArrayList<Double>();

	private Map<String, Double> toneNameFrequencyMap = new HashMap<String, Double>();

	private Map<Double, String> toneFrequencyNameMap = new HashMap<Double, String>();

	private Map<Integer, List<Double>> octaves = new HashMap<Integer, List<Double>>();


	public Scale(Musica mc, String baseToneName, String scaleType) {
		this(mc, baseToneName, scaleType, 96);
	}


	public Scale(Musica mc, String startToneName, String scaleType, int toneCount) {
		name = startToneName + " " + scaleType;
		int[] scalePattern = mc.getScalePattern(scaleType);
		double startFrequency = mc.getToneFrequency(startToneName);
		int octave = mc.getFrequencyOctave(startFrequency);

		int toneCounter = 0;
		int frequencyIndex = mc.getToneFrequencyIndex(startFrequency);
		int scaleOffset = 0;
		List<Double> octFrequencies = new ArrayList<Double>();
		while ((toneCounter < toneCount) && (frequencyIndex < mc.toneArray.length)) {
			double toneFrequency = mc.toneArray[frequencyIndex];
			toneFrequencies.add(toneFrequency);
			octFrequencies.add(toneFrequency);

			String toneName = mc.getFrequencyToneName(toneFrequency);
			toneNames.add(toneName);

			toneNameFrequencyMap.put(toneName, toneFrequency);
			toneFrequencyNameMap.put(toneFrequency, toneName);

			int step = scalePattern[scaleOffset];
			frequencyIndex += step;

			scaleOffset++;
			scaleOffset %= scalePattern.length;
			if (scaleOffset == 0) {
				scaleOffset %= scalePattern.length;
				octaves.put(octave, octFrequencies);
				octFrequencies = new ArrayList<Double>();
				octave++;
			}

			toneCounter++;
		}
	}


	public Scale(Scale that) {
		copy(that);
	}


	public Scale copy() {
		return new Scale(this);
	}


	public void copy(Scale that) {
		this.name = that.name;
		this.toneNames = new ArrayList<String>(that.toneNames);
		this.toneFrequencies = new ArrayList<Double>(that.toneFrequencies);
		this.toneNameFrequencyMap = new HashMap<String, Double>(that.toneNameFrequencyMap);
		this.toneFrequencyNameMap = new HashMap<Double, String>(that.toneFrequencyNameMap);
		this.octaves = new HashMap<Integer, List<Double>>(that.octaves);
	}


	public void setName(String name) {
		this.name = name;
	}


	public String getName() {
		return name;
	}


	public List<String> getToneNames() {
		return toneNames;
	}


	public String getToneName(double frequency) {
		return toneFrequencyNameMap.get(frequency);
	}


	public double getToneFrequency(String name) {
		return toneNameFrequencyMap.get(name);
	}


	public List<Double> getToneFrequencies() {
		return toneFrequencies;
	}


	public String getBaseNoteName() {
		return toneNames.get(0);
	}


	public double getBaseNoteFrequency() {
		return toneFrequencies.get(0);
	}


	public List<Double> getOctave(int octave) {
		return octaves.get(octave);
	}
}
